template <GLenum target>
inline TBuffer<target>::TBuffer(GLsizei size, int nbDeclarations, GLenum mode) :
_size(size), _nbDeclarations(nbDeclarations), _inc(0), _mode(mode)
{
    _VDs = new VertexDeclaration[nbDeclarations];
    for(int i=0; i<nbDeclarations; i++)
        _VDs[i].first = 0;
    glGenBuffersARB(1, &_buf);
    glBindBufferARB(target, _buf);
    glBufferDataARB(target, _size, NULL, _mode);
    glBindBufferARB(target, 0);
}

template <GLenum target>
inline TBuffer<target>::~TBuffer()
{
    glDeleteBuffersARB(1, &_buf);
    delete[] _VDs;
}

template <GLenum target>
inline GLsizei TBuffer<target>::getSize() const
{
    return _size;
}

template <GLenum target>
inline GLenum TBuffer<target>::getType() const
{
    return target;
}

template <GLenum target>
inline GLenum TBuffer<target>::getMode() const
{
    return _mode;
}

template <GLenum target>
inline GLuint TBuffer<target>::getBuffer() const
{
    return _buf;
}

template <GLenum target>
inline int TBuffer<target>::getNbDeclarations() const
{
    return _nbDeclarations;
}

template <GLenum target>
inline const VertexDeclaration &TBuffer<target>::getDeclaration(int nb) const
{
    return _VDs[nb];
}

template <GLenum target>
inline void TBuffer<target>::fill(GLsizeiptr size, const GLvoid *data, GLenum usage, GLsizei size_b)
{
    _VDs[_inc].usage = usage;
    _VDs[_inc].size_b = size_b;

    glBindBufferARB(target, _buf);
    glBufferSubDataARB(target, _VDs[_inc].first, size, data);
    glBindBufferARB(target, 0);

    if(_inc < _nbDeclarations - 1)
    {
        _inc++;
        _VDs[_inc].first = _VDs[_inc-1].first + size;
    }
}

template <GLenum target>
inline void TBuffer<target>::update(GLsizeiptr size, const GLvoid *data)
{
    glBindBufferARB(target, _buf);

    GLvoid *vbo = NULL;
    vbo = glMapBufferARB(target, GL_WRITE_ONLY);
    if(vbo != NULL)
        memcpy(vbo, data, size);
    glUnmapBufferARB(target);
    vbo = NULL;

    glBindBufferARB(target, 0);
}
